package cc.rengu.igas.opms.core.service.trans.common;

import cc.rengu.igas.opms.common.enums.PassTypeEnum;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.common.enums.SignTokenTypeEnum;
import cc.rengu.igas.opms.common.util.ParameterUtil;
import cc.rengu.igas.opms.core.service.base.ManageService;
import cc.rengu.igas.opms.facade.request.ModifySignPhoneRequest;
import cc.rengu.igas.opms.facade.response.ModifySignPhoneResponse;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.NonFinanceTxnMapper;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.NonFinanceTxnMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.NonFinanceTxn;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.SmsService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.SmsServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.GlobalTransUtil;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 修改签约手机号
 * Created by liujinan on 2020/4/16.
 * modify by wangcheng 2021-09-13
 */
public class ModifySignPhoneService extends ManageService implements TransCustomImpl {
    OrderInfo orderInfo = null;

    @Override
    protected Object bizBeforeCust() throws Exception {
        ModifySignPhoneRequest modifySignPhoneRequest = new ModifySignPhoneRequest();
        ConvertUtil.convertOutput(modifySignPhoneRequest);
        //去掉参数的空格，并对金额进行格式化
        ParameterUtil.paramertTrimAndFormatAmt(modifySignPhoneRequest);
        return modifySignPhoneRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        ModifySignPhoneResponse modifySignPhoneResponse = new ModifySignPhoneResponse();
        BizResponse<ModifySignPhoneResponse> bizResponse = new BizResponse();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);

        ModifySignPhoneRequest modifySignPhoneRequest = (ModifySignPhoneRequest) request;
        String instId = modifySignPhoneRequest.getHeader().getInstId();
        String userId = modifySignPhoneRequest.getUserId();
        String signToken = modifySignPhoneRequest.getSignToken();

        //检查会话
        UserService userService = new UserServiceImpl();
        UserInfo userInfo = userService.getUserInfo(instId, userId, modifySignPhoneRequest.getHeader().getSession());
        if (null == userInfo) {
            rglog.error("获取用户信息失败!");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }

        //获取签约信息
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        List<SignAcctInfo> signAcctInfos = signAcctInfoMapper.selectSignAcctInfoBySignToken(instId, signToken);
        if (null == signAcctInfos || signAcctInfos.isEmpty()) {
            rglog.info("签约信息不存在，instId:<{}>,signToken:<{}>,signInst:<{}>", instId, signToken, userService.getUserSignInst());
            throw new BizException(RespCodeEnum.GET_SIGN_INFO_ERROR.getRespCode(), RespCodeEnum.GET_SIGN_INFO_ERROR.getRespDesc());
        }
        signAcctInfos = signAcctInfos.stream().filter(item -> AppParamConstant.YES.equals(item.getSignStatus())
                && item.getSignAcctNo().endsWith(modifySignPhoneRequest.getPayAcctNo())
                && userId.equals(item.getUserId())).collect(Collectors.toList());
        if (signAcctInfos.isEmpty()) {
            rglog.info("不存在当前卡号有效的签约信息，userId:<{}>,signToken:<{}>,acctNo:<{}>", userId, signToken, modifySignPhoneRequest.getPayAcctNo());
            throw new BizException(RespCodeEnum.GET_SIGN_INFO_ERROR.getRespCode(), RespCodeEnum.GET_SIGN_INFO_ERROR.getRespDesc());
        }

        //签约标记类型
        SignAcctInfo oldSignAcctInfo = signAcctInfos.get(0);
        GlobalTransUtil.setCacheValue(TransCacheConstant.SIGN_ACCT_INFO, oldSignAcctInfo);
        String signTokenType = oldSignAcctInfo.getSignTokenType();

        //判断如果签约手机号与修改手机号相同则直接返回成功
        if (modifySignPhoneRequest.getPhoneNo().equals(oldSignAcctInfo.getReserveMobileNo())) {
            rglog.info("修改手机号与签约手机号相同，不做更改。modifyPhoneNo:<{}>,reserveMobileNo:<{}>", modifySignPhoneRequest.getPhoneNo(), oldSignAcctInfo.getReserveMobileNo());
            bizResponse.setResult(modifySignPhoneResponse);
            throw new BizException(RespCodeEnum.MOBILE_CANNOT_THE_SAME.getRespCode(), RespCodeEnum.MOBILE_CANNOT_THE_SAME.getRespDesc());
        }

        //根据不同的签约通道选择不同的短信验证码校验方式,校验结束之后选择发起签约
        if (PassTypeEnum.BANK_SIAN.getPassCode().equals(signTokenType)) {
            //校验短信验证码
            rglog.debug("原签约信息为本行快捷签约,signTokenType:<{}>", signTokenType);
            SmsService smsService = new SmsServiceImpl();
            smsService.verifySmsCode(instId, SmsTypeEnum.MODIFY_PHONE.getSmsType(), modifySignPhoneRequest.getSmsCode(), modifySignPhoneRequest.getSmsVerifySeqNum());
        } else if (PassTypeEnum.NCQ_SIAN.getPassCode().equals(signTokenType)) {
            rglog.debug("原签约信息非本行快捷签约,signTokenType:<{}>", signTokenType);
            NonFinanceTxnMapper nonFinanceTxnMapper = new NonFinanceTxnMapperImpl();
            NonFinanceTxn nonFinanceTxn = nonFinanceTxnMapper.selectNonFinanceTxnInfoByPrimaryKey(instId, modifySignPhoneRequest.getSmsVerifySeqNum());
            if (nonFinanceTxn == null) {
                rglog.info("非金融流水表中无该请求短信验证码交易，instId:<{}>,transSeqNum:<{}>", instId, modifySignPhoneRequest.getSmsVerifySeqNum());
                throw new BizException(RespCodeEnum.VERIFICATION_CODE_INVALID.getRespCode(), RespCodeEnum.VERIFICATION_CODE_INVALID.getRespDesc());
            }
            GlobalTransUtil.setCacheValue(TransCacheConstant.SMS_CHANNEL_RELATION_KEY, nonFinanceTxn.getRemark1());
        } else {
            rglog.info("不支持的签约通道,signTokenType:<{}>", signTokenType);
            throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
        }

        //通道调用参数配置检查
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(modifySignPhoneRequest, channelCallCfgList);

        //通道服务调用
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, (null == orderInfo) ? new OrderInfo() : orderInfo, channelCallCfg.getBizScene(), request);

        //更新签约信息中的预留手机号
        updateSignAcctInfo(modifySignPhoneRequest.getPhoneNo(), oldSignAcctInfo);

        //响应信息
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(modifySignPhoneResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        ModifySignPhoneResponse modifySignPhoneResponse = (ModifySignPhoneResponse) bizResponse.getResult();
        ConvertUtil.convertInput(modifySignPhoneResponse);
    }

    /**
     * 更新签约信息表
     *
     * @param phoneNo      手机号
     * @param signAcctInfo 签约信息
     * @throws Exception 异常
     */
    private void updateSignAcctInfo(String phoneNo, SignAcctInfo signAcctInfo) throws Exception {
        signAcctInfo.setReserveMobileNo(phoneNo);
        signAcctInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        if (0 != signAcctInfoMapper.updateSignAcctInfoByPrimaryKey(signAcctInfo)) {
            rglog.info("更新签约信息表银行预留手机号失败");
            throw new BizException(RespCodeEnum.UPDATE_SIGN_ACCT_ERROR.getRespCode(), RespCodeEnum.UPDATE_SIGN_ACCT_ERROR.getRespDesc());
        } else {
            rglog.debug("更新签约信息表银行预留手机号成功");
        }
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        List<ChannelCallCfg> channelCallCfgs = null;
        SignAcctInfo signAcctInfo = (SignAcctInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_ACCT_INFO);
        if (null != signAcctInfo) {
            if (SignTokenTypeEnum.BANK_QUICK_PAY.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                if (AcctTypeEnum.BANK_DEBIT.getAcctType().equals(signAcctInfo.getSignAcctType())) {
                    //本行借记场景
                    channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("00")).collect(Collectors.toList());
                } else if (AcctTypeEnum.BANK_CREDIT.getAcctType().equals(signAcctInfo.getSignAcctType())) {
                    //本行贷记卡场景
                    channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("01")).collect(Collectors.toList());
                }
            } else if (SignTokenTypeEnum.UPAC_TOKEN.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                //银联无跳转场景
                channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("02")).collect(Collectors.toList());
            } else if (SignTokenTypeEnum.NCQS_PAY.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                //银联无卡快捷场景
                channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("03")).collect(Collectors.toList());
            } else if (SignTokenTypeEnum.NUCC_PAY.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                //网联协议支付场景
                channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("04")).collect(Collectors.toList());
            }
        }
        if (null != channelCallCfgs) {
            if (channelCallCfgs.size() > 1) {
                rglog.error("业务场景为<{}>，调用序号为<{}>存在多条配置，请检查配置!", channelCallCfgs.get(0).getBizScene(), channelCallCfgList.get(0).getCallIndex());
                return null;
            } else {
                return channelCallCfgs.stream().findFirst().orElse(null);
            }
        }
        return null;
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        return transStatusEnum;
    }
}
